圖的走訪是一項重要的操作,主要有兩種方法:深度優先搜尋(Depth First Search,DFS)和廣度優先搜尋(Breadth-First Search,BFS)。
DFS是一種用於圖形和樹狀結構的搜索算法,用於探索所有可能的節點,直到找到目標節點或遍歷整個結構。DFS的主要思想是先往深處探索,然後回溯到之前的節點,再繼續向下一個分支探索。
DFS的實現方式可以使用遞迴或堆疊(或稱為堆棧)來追蹤節點的訪問順序。在使用遞迴的情況下,程式會自動維護呼叫堆疊,而在使用堆疊的情況下,你需要手動管理堆疊。
我們會先往深處探索,然後回溯到之前的節點
void DFS::DFS_Traversal(int s) {
vector<bool> visited(V, false); // 設定所有頂點都沒有被訪問過
stack<int> stack; // 建立一個堆疊
stack.push(s); // 將起始頂點放入堆疊
visited[s] = true; // 設定起始頂點為已訪問
while (!stack.empty()) { // 當堆疊不為空
int v = stack.top(); // 取出堆疊頂點
cout << v << " "; // 印出頂點
stack.pop(); // 將頂點從堆疊中移除
for (auto i = adj[v].begin(); i != adj[v].end(); i++) { // 對於頂點v的每一個鄰接頂點
if (!visited[*i]) { // 如果鄰接頂點沒有被訪問過
stack.push(*i); // 將鄰接頂點放入堆疊
visited[*i] = true; // 設定鄰接頂點為已訪問
}
}
}
}
深度優先搜尋是一種重要的搜尋算法,常常用於解決迷宮、拓撲排序、圖形遍歷等問題。在實際應用中,你可以根據具體問題的需求來選擇使用深度優先搜尋或其他搜尋算法。
BFS是一種搜尋算法,用於圖形和樹狀結構的探索。它的核心思想是先往相鄰的節點探索,然後逐層擴展到更遠的節點。
以下是BFS的基本工作原理:
先往相鄰的節點探索,然後逐層擴展到更遠的節點
void BFS::BFS_Traversal(int s) {
vector<bool> visited(V, false); // 設定所有頂點都沒有被訪問過
vector<int> queue; // 建立一個佇列
queue.push_back(s); // 將起始頂點放入佇列
visited[s] = true; // 設定起始頂點為已訪問
while (!queue.empty()) { // 當佇列不為空
int v = queue.front(); // 取出佇列頂點
cout << v << " "; // 印出頂點
queue.erase(queue.begin()); // 將頂點從佇列中移除
for (auto i = adj[v].begin(); i != adj[v].end(); i++) { // 對於頂點v的每一個鄰接頂點
if (!visited[*i]) { // 如果鄰接頂點沒有被訪問過
queue.push_back(*i); // 將鄰接頂點放入佇列
visited[*i] = true; // 設定鄰接頂點為已訪問
}
}
}
}
以下是深度優先搜索(DFS)和廣度優先搜索(BFS)之間的比較表
特性 | 深度優先搜索 (DFS) | 廣度優先搜索 (BFS) |
---|---|---|
適用範圍 | 樹狀結構和圖形 | 樹狀結構和圖形 |
搜索策略 | 深入優先,向深處探索 | 廣度優先,逐層探索 |
記憶體使用 | 低,使用遞迴或堆疊 | 較高,使用佇列 |
最短路徑 | 不保證找到最短路徑 | 保證找到最短路徑 |
循環 | 可能陷入無限迴圈 | 不會陷入無限迴圈 |
遞迴 | 自動維護呼叫堆疊 | 不使用遞迴 |
遍歷順序 | 深入優先,回溯到之前的節點 | 廣度優先,按層級遍歷 |
應用範圍 | 迷宮解決、拓撲排序 | 最短路徑、最小生成樹 |
優點 | 簡單易實現,適用於深度搜索問題 | 可找到最短路徑,不會陷入無限迴圈 |
缺點 | 不保證找到最短路徑,可能陷入無限迴圈 | 需要較多記憶體,較複雜的程式碼 |
總結來說,DFS主要適用於深度搜索問題,如迷宮解決和拓撲排序,但不保證找到最短路徑。BFS則適用於需要找到最短路徑的情況,並且不會陷入無限迴圈,但需要更多的記憶體和較複雜的程式碼以使用佇列來實現。選擇哪種算法取決於您的具體問題需求。
每個人都有自己獨特的生活節奏和目標,不必受到他人的壓力或期望。重要的是要找到自己的方向,以自己的步伐前進,這樣你可以更自在、更快樂地探索世界。